package legumes.client.services.util.rpc;

import java.util.ArrayList;
import java.util.List;

import legumes.client.ui.LoadingUIManager;

import com.google.gwt.core.client.GWT;

/**
 * Convenient class to call in sequence several RPC methods. Do not forget to
 * call {@link #callNext()} in onSuccess method to call the next RPC.
 * 
 * @author cpipo
 * 
 */
public class RPCCallSequencer {
	private List<Runnable> calls = new ArrayList<Runnable>();

	private int nextToCallIndex = 0;

	private String message = null;

	private boolean interrupted = false;

	public RPCCallSequencer() {
	}

	public RPCCallSequencer(String string_) {
		message = string_;
	}

	private int getPercentProgression() {
		return Math.min(100, (int) ((nextToCallIndex + 0.5) * 100)
				/ calls.size());
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message_) {
		message = message_;
	}

	void callNext() {
		if (getMessage() != null) {
			LoadingUIManager.getInstance().updateLoadingPct(getPercentProgression());
			GWT.log("progressbar : " + getPercentProgression());
		}
		if (nextToCallIndex >= calls.size() || isInterrupted()) {
			if (getMessage() != null) {
				LoadingUIManager.getInstance().hide();
			}
			return;
		}
		Runnable runnable = calls.get(nextToCallIndex++);
		runnable.run();
		if (!(runnable instanceof SequencableRPCCall)) {
			callNext();
		}
	}

	public void interruptSequence() {
		interrupted = true;
	}

	public boolean isInterrupted() {
		return interrupted;
	}

	public void callSequence() {
		if (getMessage() != null) {
			LoadingUIManager.getInstance().updateLoadingMessage(getMessage() + " Merci de patienter...");
			GWT.log("progressbar : " + getMessage() + " Merci de patienter...");
		}
		nextToCallIndex = 0;
		callNext();
	}

	public void addCall(SequencableRPCCall<?> c_) {
		c_.setSequencer(this);
		calls.add(c_);
	}

	public void addCall(int index_, SequencableRPCCall<?> c_) {
		c_.setSequencer(this);
		calls.add(index_, c_);
	}

	public void addRunnable(Runnable runnable) {
		calls.add(runnable);
	}
}
